home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJGOS106.ARJ / CONTROL.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  17KB  |  712 lines

  1. /* This is file CONTROL.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* History:87,1 */
  17. #include <dos.h>
  18. #include <dir.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <fcntl.h>
  22. #include <sys/stat.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25.  
  26. #include "build.h"
  27. #include "types.h"
  28. #include "gdt.h"
  29. #include "idt.h"
  30. #include "tss.h"
  31. #include "valloc.h"
  32. #include "utils.h"
  33. #include "syms.h"
  34. #include "graphics.h"
  35. #include "mono.h"
  36. #include "vcpi.h"
  37.  
  38. TSS *tss_ptr;
  39. int debug_mode = 0;
  40. int self_contained;
  41. long header_offset = 0;
  42. int use_ansi=0;
  43. int use_mono=0;
  44. int redir_1_mono=0;
  45. int redir_2_mono=0;
  46. int redir_2_1=0;
  47. int redir_1_2=0;
  48.  
  49. static int old_video_mode;
  50. static int globbing=1;
  51.  
  52. int16 ems_handle=0;        /*  Get EMS Handle  */
  53. word16 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  54.  
  55. extern near go32();
  56. extern near go_real_mode();
  57. extern void vcpi_flush();    /*  VCPI Memory All Cleared  */
  58.  
  59. extern int was_exception;
  60. extern near ivec0(), ivec1(), ivec7(), ivec75();
  61. extern near interrupt_common(), page_fault();
  62. extern near v74_handler(), v78_handler(), v79_handler();
  63.  
  64. extern short new_pic;
  65. extern word32 far *pd;
  66.  
  67. short _openfd[255] = {
  68.   0x2001,0x2002,0x2002,0xa004,0xa002,0xffff,0xffff,0xffff,
  69.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  70.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  71.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  72.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  73.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  74.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  75.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  76.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  77.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  78.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  79.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  80.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  81.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  82.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  83.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  84.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  85.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  86.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  87.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  88.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  89.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  90.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  91.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  92.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  93.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  94.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  95.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  96.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  97.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  98.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  99.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  100. };
  101.  
  102. bump_file_limit()
  103. {
  104.   if (((((int)_osmajor)<<8)|_osminor) < 0x0303)
  105.     return;
  106.   _AH = 0x67;
  107.   _BX = 255;
  108.   geninterrupt(0x21);
  109. }
  110.  
  111. initialize_printer()
  112. {
  113.   _BX=4;
  114.   _AH=0x44;
  115.   _AL=0x01;
  116.   _DX=0xa0;
  117.   geninterrupt(0x21);
  118.   setmode(4, O_BINARY);
  119. }
  120.  
  121. fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  122. {
  123.   GDT_S *g;
  124.   g = gdt+sel;
  125.   if (G & 2)
  126.     limit = limit >> 12;
  127.   g->lim0 = limit & 0xffff;
  128.   g->lim1 = (limit>>16) & 0x0f;
  129.   g->base0 = base & 0xffff;
  130.   g->base1 = (base>>16) & 0xff;
  131.   g->base2 = (base>>24) & 0xff;
  132.   g->stype = type;
  133.   g->lim1 |= G * 0x40;
  134. }
  135.  
  136. word32 ptr2linear(void far *ptr)
  137. {
  138.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  139. }
  140.  
  141. setup_tss(TSS *t, int (*eip)())
  142. {
  143.   memset(t, 0, sizeof(TSS));
  144.   t->tss_cs = g_rcode*8;
  145.   t->tss_eip = (long)FP_OFF(eip);
  146.   t->tss_ss = g_rdata*8;
  147.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  148.   t->tss_ds = g_rdata*8;
  149.   t->tss_es = g_rdata*8;
  150.   t->tss_fs = g_rdata*8;
  151.   t->tss_gs = g_rdata*8;
  152.   t->tss_eflags = 0x0200;
  153.   t->tss_iomap = 0xffff; /* no map */
  154. }
  155.  
  156. exit_func()
  157. {
  158.   int i;
  159.   dalloc_uninit();
  160.   uninit_controllers();
  161.   xms_free();
  162.   if ((ems_handle)&&(ems_handle != -1))
  163.     ems_free(ems_handle);    /*  Deallocated EMS Page    */
  164.   if (vcpi_installed)
  165.     vcpi_flush();        /*  Deallocated VCPI Pages  */
  166.  
  167. #if TOPLINEINFO
  168.   for (i=0; i<80; i++)
  169.     poke(screen_seg, i*2, 0x0720);
  170. #endif
  171. }
  172.  
  173. int ctrl_c_flag = 0;
  174.  
  175. ctrlbrk_func()
  176. {
  177. #if DEBUGGER
  178.   ctrl_c_flag = 1;
  179. #else
  180.   exit(3);
  181. #endif
  182. }
  183.  
  184. usage(char *s)
  185. {
  186.   printf("Usage: %s [program [options . . . ]]\n", s);
  187.   _exit(1);
  188. }
  189.  
  190. int have_80387;
  191. int use_xms=0;
  192. static word32 push32(void *ptr, int len);
  193.  
  194. setup_idt_task(int which, int tss)
  195. {
  196.   idt[which].selector = tss*8;
  197.   idt[which].stype = 0x8500;
  198.   idt[which].offset0 = 0;
  199.   idt[which].offset1 = 0;
  200. }
  201.  
  202. main(int argc, char **argv, char **envp)
  203. {
  204.   int i, n, set_brk=0, emu_installed=0;
  205.   struct stat stbuf;
  206.   char *cp, *path, *argv0, *emu_fn=0;
  207.   unsigned short header[3];
  208.  
  209.   bump_file_limit();
  210.  
  211.   if (xms_installed())
  212.     use_xms = 1;
  213.   old_video_mode = peekb(0x40, 0x49);
  214.  
  215.   if (strcmp(argv[1], "!proxy") == 0)
  216.   {
  217.     int oseg, optr, i;
  218.     int far *oargv;
  219.     char far *oargve;
  220.     sscanf(argv[2], "%x", &argc);
  221.     sscanf(argv[3], "%x", &oseg);
  222.     sscanf(argv[4], "%x", &optr);
  223.     oargv = MK_FP(oseg, optr);
  224.     argv = (char **)malloc(sizeof(char *) * (argc+1));
  225.     for (i=0; i<argc+1; i++)
  226.     {
  227.       if (oargv[i] == 0)
  228.       {
  229.         argv[i] = 0;
  230.         break;
  231.       }
  232.       oargve = MK_FP(oseg, oargv[i]);
  233.       for (optr=0; oargve[optr]; optr++);
  234.       argv[i] = (char *)malloc(optr+1);
  235.       for (optr=0; oargve[optr]; optr++)
  236.         argv[i][optr] = oargve[optr];
  237.       argv[i][optr] = 0;
  238.     }
  239.   }
  240.  
  241.   ems_handle = emm_present();
  242.   switch (cputype())
  243.   {
  244.     case 1:
  245.       if ((ems_handle)&&(ems_handle != -1))
  246.     ems_free(ems_handle);
  247.       fprintf(stderr, "CPU must be a 386 to run this program.\n");
  248.       exit(1);
  249.     case 2:
  250.       if (ems_handle)
  251.     {
  252.     if (vcpi_installed = vcpi_present())
  253.       break;
  254.     else if (ems_handle != -1)
  255.       ems_free(ems_handle);
  256.     }
  257.       fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
  258.       exit(1);
  259.   }
  260.  
  261.   if (peekb(0x40,0x49) == 7)
  262.     screen_seg = 0xb000;
  263.  
  264.   _fmode = O_BINARY;
  265.  
  266.   cp = getenv("GO32");
  267.   path = 0;
  268.   if (cp)
  269.     while (1)
  270.     {
  271.       char sw[100];
  272.       char val[100];
  273.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  274.         break;
  275.       cp += i;
  276.       if (stricmp(sw, "ansi") == 0)
  277.         use_ansi = 1;
  278.       else if (stricmp(sw, "mono") == 0)
  279.         use_mono = 1;
  280.       else if (stricmp(sw, "2r1") == 0)
  281.         redir_2_1 = 1;
  282.       else if (stricmp(sw, "1r2") == 0)
  283.         redir_1_2 = 1;
  284.       else if (stricmp(sw, "2rm") == 0)
  285.         redir_2_mono = 1;
  286.       else if (stricmp(sw, "1rm") == 0)
  287.         redir_1_mono = 1;
  288.       else if (stricmp(sw, "glob") == 0)
  289.         globbing = 1;
  290.       else if (stricmp(sw, "noglob") == 0)
  291.         globbing = 0;
  292.       else
  293.       {
  294.         val[0] = 0;
  295.         sscanf(cp, "%s%n", val, &i);
  296.         cp += i;
  297.         if (val[0] == 0)
  298.           break;
  299.       }
  300.       if (stricmp(sw, "driver") == 0)
  301.       {
  302.         if (path) free(path);
  303.         path = strdup(val);
  304.       }
  305.       else if (stricmp(sw, "tw") == 0)
  306.         gr_def_tw = atoi(val);
  307.       else if (stricmp(sw, "th") == 0)
  308.         gr_def_th = atoi(val);
  309.       else if (stricmp(sw, "gw") == 0)
  310.         gr_def_gw = atoi(val);
  311.       else if (stricmp(sw, "gh") == 0)
  312.         gr_def_gh = atoi(val);
  313. #ifndef NONEWDRIVER
  314.       else if (stricmp(sw, "nc") == 0)
  315.         gr_def_numcolor = atoi(val);
  316. #endif
  317.       else if (stricmp(sw, "emu") == 0)
  318.       {
  319.         if (emu_fn) free(emu_fn);
  320.         emu_fn = strdup(val);
  321.       }
  322.     }
  323. #if ! DEBUGGER
  324. #if ! TOPLINEINFO
  325.   use_mono = 0;
  326. #endif
  327. #endif
  328.   setup_graphics_driver(path);
  329.   if (path) free(path);
  330.   if (use_mono)
  331.   {
  332.     use_ansi = 0;
  333.     screen_seg = 0xb000;
  334.   }
  335.  
  336.   setbuf(stdin, 0);
  337.   atexit((atexit_t)exit_func);
  338.   ctrlbrk(ctrlbrk_func);
  339.   n = (int)ivec1-(int)ivec0;
  340.   for (i=0; i<256; i++)
  341.   {
  342.     idt[i].selector = g_rcode*8;
  343.     idt[i].stype = 0x8e00;
  344.     idt[i].offset0 = FP_OFF((int)ivec0+n*i);
  345.     idt[i].offset1 = 0;
  346.   }
  347.   setup_idt_task(14, g_ptss);
  348.  
  349.   cp = getenv("387");
  350.   if (cp)
  351.     if (tolower(cp[0]) == 'n')
  352.       have_80387 = 0;
  353.     else if (tolower(cp[0]) == 'y')
  354.       have_80387 = 1;
  355.     else
  356.       have_80387 = detect_80387();
  357.   else
  358.     have_80387 = detect_80387();
  359.   if (have_80387)
  360.   {
  361.     idt[7].offset0 = (int)ivec7;
  362.     idt[7].offset1 = 0;
  363.     idt[0x75].offset0 = (int)ivec75;
  364.     idt[0x75].offset1 = 0;
  365.   }
  366.  
  367.   if (cp && (tolower(cp[0]) == 'q'))
  368.     if (have_80387)
  369.       printf("An 80387 has been detected.\n");
  370.     else
  371.       printf("No 80387 has been detected.\n");
  372.  
  373.   fillgdt(g_zero, 0, 0, 0, 0);
  374.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  375.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  376.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  377.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  378.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  379.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  380.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  381.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 3);
  382.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 3);
  383.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 3);
  384.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 3);
  385.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  386.   fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  387.   fillgdt(g_v74, sizeof(TSS), ptr2linear(&v74_tss), 0x89, 3);
  388.   fillgdt(g_v78, sizeof(TSS), ptr2linear(&v78_tss), 0x89, 3);
  389.   fillgdt(g_v79, sizeof(TSS), ptr2linear(&v79_tss), 0x89, 3);
  390.  
  391.   setup_tss(&c_tss, go_real_mode);
  392.   setup_tss(&a_tss, go_real_mode);
  393.   setup_tss(&o_tss, go_real_mode);
  394.   setup_tss(&f_tss, go_real_mode);
  395.   setup_tss(&i_tss, interrupt_common);
  396.   setup_tss(&p_tss, page_fault);
  397.   setup_tss(&v74_tss, v74_handler);
  398.   setup_tss(&v78_tss, v78_handler);
  399.   setup_tss(&v79_tss, v79_handler);
  400.   tss_ptr = &a_tss;
  401.  
  402.   argv0 = argv[0];
  403.   for (i=0; argv0[i]; i++)
  404.   {
  405.     if (argv0[i] == '\\')
  406.       argv0[i] = '/';
  407.     argv0[i] = tolower(argv0[i]);
  408.   }
  409.   if (strcmp(argv[1], "-nobrk") == 0)
  410.   { /* for backwards compatibility only - DO NOT USE */
  411.     set_brk=1;
  412.     argv++;
  413.     argc--;
  414.   }
  415.  
  416. #if TOPLINEINFO
  417.   for (i=0; i<80; i++)
  418.     poke(screen_seg, i*2, 0x0720);
  419. #endif
  420.  
  421.   self_contained = 0;
  422.   n = open(argv0, O_RDONLY|O_BINARY);
  423.   header[0] = 0;
  424.   read(n, header, sizeof(header));
  425.   if (header[0] == 0x5a4d)
  426.   {
  427.     header_offset = (long)header[1] + (long)header[2]*512L - 512L;
  428.     lseek(n, header_offset, 0);
  429.     header[0] = 0;
  430.     read(n, header, sizeof(header));
  431.     if (header[0] == 0x010b)
  432.       self_contained = 1;
  433.   }
  434.   close(n);
  435.  
  436.   if (self_contained)
  437.   {
  438. #if DEBUGGER
  439.     debug_mode = 1;
  440. #else
  441.     debug_mode = 0;
  442. #endif
  443.     paging_set_file(argv0);
  444.     emu_installed = emu_install(emu_fn);
  445.     set_command_line(argv, envp);
  446. #if DEBUGGER
  447.     syms_init(argv0);
  448. #endif
  449.   }
  450.   else
  451.   {
  452.     header_offset = 0;
  453.     for (cp=argv0; *cp; cp++)
  454.       if (*cp == '.')
  455.         path = cp;
  456.     *path = 0;
  457.     if (stat(argv0, &stbuf)) /* not found */
  458.     {
  459.       fprintf(stderr, "%s.exe version 1.06 Copyright (C) 1991 DJ Delorie\n",
  460.               argv0);
  461.       debug_mode = 1;
  462.       if (argv[1] == 0)
  463.         usage(argv0);
  464.       paging_set_file(argv[1]);
  465.       emu_installed = emu_install(emu_fn);
  466.       set_command_line(argv+1, envp);
  467. #if DEBUGGER
  468.       syms_init(argv[1]);
  469. #endif
  470.     }
  471.     else /* found */
  472.     {
  473.       debug_mode = 0;
  474.       paging_set_file(argv0);
  475.       emu_installed = emu_install(emu_fn);
  476.       set_command_line(argv, envp);
  477. #if DEBUGGER
  478.       syms_init(argv0);
  479. #endif
  480.     }
  481.   }
  482.  
  483.   if (set_brk)
  484.     paging_brk(0x8fffffffL);
  485.  
  486.   dalloc_init();
  487.   init_controllers();
  488.  
  489.   setup_idt_task(0x74, g_v74);
  490.   setup_idt_task(new_pic, g_v78);
  491.   setup_idt_task(new_pic+1, g_v79);
  492.  
  493.   if (emu_installed)
  494.   {
  495.     push32(&(a_tss.tss_eip), 4);
  496.     a_tss.tss_eip = 0xb0000020;
  497.   }
  498. #if DEBUGGER
  499.   debugger();
  500.   if (peekb(0x40, 0x49) != old_video_mode)
  501.   {
  502.     _AX = old_video_mode;
  503.     geninterrupt(0x10);
  504.   }
  505.   return 0;
  506. #else
  507.   go_til_stop();
  508.   if (tss_ptr->tss_irqn == 0x79)
  509.     fprintf(stderr, "Ctrl-C Hit!  Stopped at address %lx\n", tss_ptr->tss_eip);
  510.   else
  511.     fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
  512.   return 1;
  513. #endif
  514. }
  515.  
  516. #if !DEBUGGER
  517. gdtprint(i)
  518. {
  519.   printf("0x%02x: base=%02x%02x%04x lim=%02x%04x G=%d type=%02x\n",
  520.     i*8, gdt[i].base2, gdt[i].base1, gdt[i].base0,
  521.     gdt[i].lim1&0x0f, gdt[i].lim0, gdt[i].lim1>>6, gdt[i].stype);
  522. }
  523. #endif
  524.  
  525. static word32 push32(void *ptr, int len)
  526. {
  527.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  528.   {
  529.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  530.     page_in();
  531.   }
  532.   a_tss.tss_esp -= len;
  533.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  534.   memput(a_tss.tss_esp+ARENA, ptr, len);
  535.   return a_tss.tss_esp;
  536. }
  537.  
  538. static int fscan_q(FILE *f, char *buf)
  539. {
  540.   char *ibuf = buf;
  541.   int c, quote=-1, gotsome=0, addquote=0;
  542.   while ((c = fgetc(f)) != EOF)
  543.   {
  544.     if (c == '\\')
  545.     {
  546.       char c2 = fgetc(f);
  547.       if (! strchr("\"'`\\ \t\n\r", c2))
  548.         *buf++ = c;
  549.       *buf++ = c2;
  550.       addquote = 0;
  551.     }
  552.     else if (c == quote)
  553.     {
  554.       quote = -1;
  555.       if (c == '\'')
  556.         addquote = 1;
  557.     }
  558.     else if (isspace(c) && (quote==-1))
  559.     {
  560.       if (gotsome)
  561.       {
  562.         if (addquote)
  563.           *buf++ = '\'';
  564.         *buf = 0;
  565.         return 1;
  566.       }
  567.       addquote = 0;
  568.     }
  569.     else
  570.     {
  571.       if ((quote == -1) && ((c == '"') || (c == '\'')))
  572.       {
  573.         quote = c;
  574.         gotsome=1;
  575.         if ((c == '\'') && (buf == ibuf))
  576.           *buf++ = c;
  577.       }
  578.       else
  579.       {
  580.         *buf++ = c;
  581.         gotsome=1;
  582.       }
  583.       addquote = 0;
  584.     }
  585.   }
  586.   return 0;
  587. }
  588.  
  589. static glob(char *buf, int (*func)())
  590. {
  591.   if (globbing && strpbrk(buf, "*?"))
  592.   {
  593.     char *dire, *cp;
  594.     struct ffblk ff;
  595.     int done, upcase=0;
  596.     done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH);
  597.     if (done)
  598.       func(buf);
  599.     else
  600.     {
  601.       char nbuf[80];
  602.       strcpy(nbuf, buf);
  603.       for (dire=cp=nbuf; *cp; cp++)
  604.       {
  605.         if (strchr("/\\:", *cp))
  606.           dire = cp + 1;
  607.         if (isupper(*cp))
  608.           upcase = 1;
  609.       }
  610.       while (!done)
  611.       {
  612.         strcpy(dire, ff.ff_name);
  613.         if (!upcase)
  614.           strlwr(dire);
  615.         func(nbuf);
  616.         done = findnext(&ff);
  617.       }
  618.     }
  619.   }
  620.   else
  621.     func(buf);
  622. }
  623.  
  624. static foreach_arg(char **argv, int (*func)())
  625. {
  626.   int i;
  627.   char firstc;
  628.   FILE *f;
  629.   char buf[80];
  630.   for (i=0; argv[i]; i++)
  631.   {
  632.     if (argv[i][0] == '@')
  633.     {
  634.       f = fopen(argv[i]+1, "rt");
  635.       while (fscan_q(f, buf) == 1)
  636.       {
  637.         if (!strcmp(buf, "\032"))
  638.           continue;
  639.         glob(buf, func);
  640.       }
  641.       fclose(f);
  642.     }
  643.     else
  644.       glob(argv[i], func);
  645.   }
  646. }
  647.  
  648. static int num_actual_args;
  649.  
  650. static just_incr()
  651. {
  652.   num_actual_args++;
  653. }
  654.  
  655. static word32 *a;
  656.  
  657. pusharg(char *ar)
  658. {
  659.   int s = strlen(ar);
  660.   if ((ar[0] == '\'') && (ar[s-1] == '\''))
  661.   {
  662.     ar[s-1] = '\0';
  663.     ar++;
  664.   }
  665.   a[num_actual_args] = push32(ar, s+1);
  666.   num_actual_args++;
  667. }
  668.  
  669. set_command_line(char **argv, char **envv)
  670. {
  671.   unsigned envc;
  672.   word32 *e, v, argp, envp;
  673.  
  674.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  675.   page_in();
  676.  
  677.   num_actual_args = 0;
  678.   foreach_arg(argv, just_incr);
  679.  
  680.   for (envc=0; envv[envc]; envc++);
  681.   e = (word32 *)malloc((envc+1)*sizeof(word32));
  682.   if (e == 0)
  683.   {
  684.     printf("Fatal! no memory to copy environment\n");
  685.     exit(1);
  686.   }
  687.   for (envc=0; envv[envc]; envc++)
  688.   {
  689.     v = push32(envv[envc], strlen(envv[envc])+1);
  690.     e[envc] = v;
  691.   }
  692.   e[envc] = 0;
  693.  
  694.   a = (word32 *)malloc((num_actual_args+1)*sizeof(word32));
  695.   if (a == 0)
  696.   {
  697.     printf("Fatal! no memory to copy arguments\n");
  698.     exit(1);
  699.   }
  700.   num_actual_args = 0;
  701.   foreach_arg(argv, pusharg);
  702.   a[num_actual_args] = 0;
  703.  
  704.   envp = push32(e, (envc+1)*sizeof(word32));
  705.   argp = push32(a, (num_actual_args+1)*sizeof(word32));
  706.  
  707.   push32(&envp, sizeof(word32));
  708.   push32(&argp, sizeof(word32));
  709.   v = num_actual_args;
  710.   push32(&v, sizeof(word32));
  711. }
  712.